package com.piece.core.log.config;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.piece.core.framework.util.basic.SpringUtil;
import com.piece.core.framework.util.location.IPAddressFactory;
import com.piece.core.framework.util.location.IPLocation;
import com.piece.core.framework.util.net.IpUtil;
import com.piece.core.log.client.dto.VisitInfoDTO;
import eu.bitwalker.useragentutils.UserAgent;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求来源信息线程
 */
@Slf4j
public class RequestContextHolder {

    /**
     * 支持父子线程之间的数据传递
     */
    private static final ThreadLocal<Map<String, String>> CONTEXT = new TransmittableThreadLocal<>();

    public static void set(HttpServletRequest request, String userAgent) {
        IPAddressFactory ipAddressService = SpringUtil.getBean(IPAddressFactory.class);
        Map<String, String> map = new HashMap();
        try {
            String ip = IpUtil.getIp(request, false);
            map.put("ip", ip);
            IPLocation location = ipAddressService.getIPLocation(ip);
            map.put("area", location.getArea());
            map.put("city", location.getCity());
            map.put("userAgent", userAgent);
        } catch (Exception e) {
            log.error("获取线程请求数据异常：{}", e.getMessage());
        }
        CONTEXT.set(map);
    }

    public static VisitInfoDTO get() {
        VisitInfoDTO visitInfo = new VisitInfoDTO();
        Map<String, String> requestInfo = CONTEXT.get();
        if (null == requestInfo || requestInfo.isEmpty()) {
            return visitInfo;
        }

        visitInfo.setIp(requestInfo.get("ip"));
        visitInfo.setArea(requestInfo.get("area"));
        visitInfo.setCity(requestInfo.get("city"));
        // 记录操作系统信息
        UserAgent userAgent = UserAgent.parseUserAgentString(requestInfo.get("userAgent"));
        visitInfo.setBrowser(userAgent.getBrowser().getName());
        visitInfo.setOs(userAgent.getOperatingSystem().getName());
        return visitInfo;
    }

    public static void clear() {
        CONTEXT.remove();
    }
}
